﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Dev2419a_LunarLander3D
{
    /// <summary>
    /// Classe responsável pelo funcionamento do jogo
    /// </summary>
    class Jogo
    {
        internal SpriteFont fontHUD;

        private SpriteBatch spriteBatch;
        private Effect effect;

        private Viewport mapViewport;
        private Viewport defaultViewport;
        private Matrix mapViewMatrix;
        private Matrix mapProjectionMatrix;

        private Matrix viewMatrix;
        private Matrix projectionMatrix;

        private Matrix worldMatrix;

        private float angle = 0f;
        private float zoom = 1f;
        private Vector3 posInicialCamera = new Vector3(60, 80, -80); // Constante para guardar a posição inicial da câmera
        private Vector3 posCamera; // Variável que guarda a posição da câmera durente o jogo

        Texture2D heightmap;
        Texture2D radar;

        private int terrainWidth;
        private int terrainHeight;
        private float[,] heightData;

        private VertexBuffer myVertexBuffer;
        private IndexBuffer myIndexBuffer;
        private VertexPositionColorNormal[] vertices;
        private int[] indices;

        private GraphicsDevice device;

        int areaPouso = 3;
        Terreno terreno;

        /// <summary>
        /// nova variável para o céu, todo dentro das pastas sky
        /// </summary>
        SkySphere skySphere;

        public Jogo(ContentManager Content,GraphicsDeviceManager graphics, Game1 game1)
        {
            // Atribuindo o valor inicial da câmera para a variável
            posCamera = posInicialCamera;

            //carrega coisas do content
            heightmap = Content.Load<Texture2D>("heightmap");
            effect = Content.Load<Effect>("effects");
            device = graphics.GraphicsDevice;

            //tamanho da imagem == tamanho do terreno
            //                 true
            terrainHeight = heightmap.Bounds.Height;
            terrainWidth =  heightmap.Bounds.Width;

            //vejam a classe terreno
            Terreno T = new Terreno(this.device,heightmap);
            T.montaTerreno(out heightData, out myVertexBuffer, out myIndexBuffer, out vertices, out indices);
            terreno = new Terreno(this.device, heightmap);
            terreno.montaTerreno(out heightData, out myVertexBuffer, out myIndexBuffer, out vertices, out indices);

            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, device.Viewport.AspectRatio, 0.1f, 300.0f);

            radar = Content.Load<Texture2D>("Radar");

            defaultViewport = device.Viewport;
            mapViewport = new Viewport(60, 60, device.Viewport.Width / 4, device.Viewport.Height / 4);

            viewMatrix = Matrix.CreateLookAt(posCamera, new Vector3(0, 0, 0), new Vector3(0, 1, 0));

            mapViewMatrix = Matrix.CreateOrthographic(5,5,.1f,300);

            skySphere = new SkySphere(Content, device,
                Content.Load<TextureCube>("Sky/Black_sky"));

        }
        public void Update(GameTime gameTime, KeyboardState keyState)
        {

            //cria camera
            viewMatrix = Matrix.CreateLookAt(posCamera, new Vector3(0, 0, 0), new Vector3(0, 1, 0));
 
        }

        internal void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

            device.Viewport = defaultViewport;

            worldMatrix = Matrix.Identity;

            skySphere.Draw(viewMatrix, projectionMatrix, posCamera);

            effect.CurrentTechnique = effect.Techniques["Colored"];

            Vector3 lightDirection = new Vector3(1.0f, -1.0f, -1.0f);
            lightDirection.Normalize();
            
            effect.Parameters["xLightDirection"].SetValue(lightDirection);
            effect.Parameters["xAmbient"].SetValue(0.1f); effect.Parameters["xEnableLighting"].SetValue(true);
            effect.Parameters["xView"].SetValue(viewMatrix);
            effect.Parameters["xProjection"].SetValue(projectionMatrix);
            effect.Parameters["xWorld"].SetValue(worldMatrix);

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
            }

            device.Indices = myIndexBuffer;
            device.SetVertexBuffer(myVertexBuffer);
            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);

            device.Viewport = mapViewport;

            effect.Parameters["xView"].SetValue(Matrix.CreateLookAt(new Vector3(posCamera.X, 90, posCamera.Z), Vector3.Zero, Vector3.Up));

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
            }

            device.Indices = myIndexBuffer;
            device.SetVertexBuffer(myVertexBuffer);
            device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);

            //tem que devolver o viewport ao original porque é usado depois 
            //para desenhar a nave
            device.Viewport = defaultViewport;
        }

        public Vector3 getPosCamera()
        {
            return posCamera;
        }

        public void setPosCamera(Vector3 pos)
        {
            this.posCamera = pos;
        }
        public float getTerrainHeight(Vector3 pos)
        {
            return terreno.getTerrainHeight(pos);
        }

        public void Reset(HUD hud, Nave nave)
        {
            nave.Reset();
            posCamera = posInicialCamera;
        }
    }
}
